export class GIFRecorder {
    constructor(canvas, fps = 10) {
        this.canvas = canvas;
        this.fps = fps;
        this.frames = [];
        this.isRecording = false;
        this.frameInterval = 1000 / fps;
        this.lastFrameTime = 0;
        this.recordingInterval = null;
    }

    start() {
        if (this.isRecording) return;
        
        this.isRecording = true;
        this.frames = [];
        this.lastFrameTime = 0;
        
        // Use requestAnimationFrame for consistent frame capture
        const captureFrame = (timestamp) => {
            if (!this.isRecording) return;
            
            if (timestamp - this.lastFrameTime >= this.frameInterval) {
                this.captureFrame();
                this.lastFrameTime = timestamp;
            }
            
            requestAnimationFrame(captureFrame);
        };
        
        requestAnimationFrame(captureFrame);
    }

    stop() {
        this.isRecording = false;
        if (this.recordingInterval) {
            clearInterval(this.recordingInterval);
            this.recordingInterval = null;
        }
    }

    captureFrame() {
        const dataURL = this.canvas.toDataURL('image/png');
        this.frames.push(dataURL);
    }

    async generateGIF() {
        if (this.frames.length === 0) {
            throw new Error('No frames recorded');
        }

        // Create a simple GIF using canvas-to-blob and gif.js approach
        // This is a simplified version that creates an animated PNG as fallback
        return this.createAnimatedImage();
    }

    async createAnimatedImage() {
        // Create a canvas-based animated image sequence
        const tempCanvas = document.createElement('canvas');
        const tempCtx = tempCanvas.getContext('2d');
        tempCanvas.width = this.canvas.width;
        tempCanvas.height = this.canvas.height;

        const encoder = new GIFEncoder(tempCanvas.width, tempCanvas.height);
        encoder.setRepeat(0); // 0 = repeat forever
        encoder.setDelay(this.frameInterval);
        encoder.setQuality(10); // 1-20, 10 is good balance

        encoder.start();

        for (const frame of this.frames) {
            const img = new Image();
            img.src = frame;
            await new Promise(resolve => {
                img.onload = () => {
                    tempCtx.clearRect(0, 0, tempCanvas.width, tempCanvas.height);
                    tempCtx.drawImage(img, 0, 0);
                    encoder.addFrame(tempCtx);
                    resolve();
                };
            });
        }

        encoder.finish();
        return encoder.stream().getData();
    }

    getFrameCount() {
        return this.frames.length;
    }

    clear() {
        this.frames = [];
        this.isRecording = false;
    }
}

// Simple GIF encoder for basic functionality
class GIFEncoder {
    constructor(width, height) {
        this.width = width;
        this.height = height;
        this.frames = [];
        this.repeat = -1;
        this.delay = 100;
        this.quality = 10;
    }

    setRepeat(repeat) {
        this.repeat = repeat;
    }

    setDelay(delay) {
        this.delay = delay;
    }

    setQuality(quality) {
        this.quality = quality;
    }

    start() {
        // Initialize GIF header
    }

    addFrame(ctx) {
        const imageData = ctx.getImageData(0, 0, this.width, this.height);
        this.frames.push(imageData);
    }

    finish() {
        // Process frames and create GIF
    }

    stream() {
        return {
            getData: () => {
                return this.createSimpleAnimatedPNG();
            }
        };
    }

    createSimpleAnimatedPNG() {
        // Create a simple animated GIF-like sequence
        // This is a placeholder for a full GIF implementation
        return this.frames;
    }
}

// Fallback implementation using WebM for modern browsers
export class WebMRecorder {
    constructor(canvas, fps = 10) {
        this.canvas = canvas;
        this.fps = fps;
        this.mediaRecorder = null;
        this.recordedChunks = [];
        this.isSupported = this.checkSupport();
    }

    checkSupport() {
        return !!(this.canvas.captureStream && window.MediaRecorder);
    }

    async start() {
        if (!this.isSupported) {
            alert('Your browser does not support video recording. Please use a modern browser like Chrome, Firefox, or Edge.');
            return false;
        }

        try {
            const stream = this.canvas.captureStream(this.fps);
            this.recordedChunks = [];
            
            // Try different MIME types for better compatibility
            const mimeTypes = [
                'video/webm;codecs=vp9',
                'video/webm;codecs=vp8',
                'video/webm',
                'video/mp4'
            ];
            
            let mimeType = null;
            for (const type of mimeTypes) {
                if (MediaRecorder.isTypeSupported(type)) {
                    mimeType = type;
                    break;
                }
            }
            
            if (!mimeType) {
                alert('Your browser does not support any video formats for recording.');
                return false;
            }

            this.mediaRecorder = new MediaRecorder(stream, { mimeType });

            this.mediaRecorder.ondataavailable = (event) => {
                if (event.data.size > 0) {
                    this.recordedChunks.push(event.data);
                }
            };

            this.mediaRecorder.onerror = (event) => {
                console.error('MediaRecorder error:', event.error);
                alert('Error starting recording: ' + event.error.message);
            };

            this.mediaRecorder.start();
            return true;
        } catch (error) {
            console.error('Failed to start recording:', error);
            alert('Failed to start recording: ' + error.message);
            return false;
        }
    }

    stop() {
        if (this.mediaRecorder && this.mediaRecorder.state === 'recording') {
            this.mediaRecorder.stop();
        }
    }

    async getBlob() {
        return new Promise((resolve, reject) => {
            if (!this.isSupported) {
                reject(new Error('Recording not supported'));
                return;
            }

            if (this.recordedChunks.length === 0) {
                reject(new Error('No recording data available'));
                return;
            }

            if (this.mediaRecorder && this.mediaRecorder.state === 'recording') {
                this.mediaRecorder.onstop = () => {
                    resolve(this.createBlob());
                };
                this.mediaRecorder.stop();
            } else {
                resolve(this.createBlob());
            }
        });
    }

    createBlob() {
        const mimeType = this.mediaRecorder?.mimeType || 'video/webm';
        return new Blob(this.recordedChunks, { type: mimeType });
    }

    async download(filename = 'sorting-visualization.webm') {
        try {
            const blob = await this.getBlob();
            if (blob.size === 0) {
                alert('No recording data available');
                return;
            }
            
            const url = URL.createObjectURL(blob);
            const a = document.createElement('a');
            a.href = url;
            a.download = filename;
            a.style.display = 'none';
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
            URL.revokeObjectURL(url);
        } catch (error) {
            console.error('Download failed:', error);
            alert('Download failed: ' + error.message);
        }
    }

    clear() {
        this.recordedChunks = [];
    }
}